package net.boyandi.picback;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.SpringLayout;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.table.DefaultTableModel;

import org.apache.log4j.Logger;

import at.fhj.utils.swing.ButtonAreaLayout;
import at.fhj.utils.swing.FancyTable;

/**
 * @author Ilya Boyandin
 */
public class SettingsDialog extends JDialog {
    
    private static Logger logger = Logger.getLogger(SettingsDialog.class.getName());

    private static final long serialVersionUID = -7160737602136900061L;
    private final Settings settings;
    private SettingsTableModel tableModel;

    private JTable foldersTable;

    private final JButton okButton;

    private JTextField backupDestFolder;

    public SettingsDialog(final PicBack picBack) {
        super(picBack, "Settings");
        
        settings = new Settings(picBack.getSettings());
        setModal(true);

        final JPanel panel = new JPanel(new BorderLayout());
        panel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
        
        final JTabbedPane tabPane = new JTabbedPane();
        tabPane.addTab("Scanning", createFoldersTab());
        tabPane.addTab("Backup", createBackupDestinationTab());

        panel.add(tabPane, BorderLayout.CENTER);

        
        JPanel buttonsPanel = new JPanel(new ButtonAreaLayout(3, 3));
        
        okButton = new JButton("OK");
        okButton.setAlignmentX(JButton.RIGHT_ALIGNMENT);
        okButton.addActionListener(new AbstractAction() {
            private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent e) {
                boolean ok = true;
                try {
                    String destFolder = backupDestFolder.getText().trim();
                    if (destFolder.length() > 0) {
                        settings.setBackupDestinationFolder(destFolder);
                    }
                } catch (IOException ex) {
                    JOptionPane.showMessageDialog(SettingsDialog.this,
                            "Couldn't set destination folder: " + ex.getMessage());
                    logger.error("Couldn't set destination folder", ex);
                    backupDestFolder.requestFocus();
                    ok = false;
                }
                if (ok) {
                    picBack.setSettings(settings);
                    dispose();
                }
            }
        });


        buttonsPanel.add(okButton);
        
        

        final JButton cancelButton = new JButton("Cancel");
        cancelButton.setAlignmentX(JButton.RIGHT_ALIGNMENT);
        final AbstractAction cancelAction = new AbstractAction() {
            private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent e) {
                dispose();
            }
        };
        cancelButton.addActionListener(cancelAction);

        buttonsPanel.add(cancelButton);
        
        // close by escape
        KeyStroke escape = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false);
        getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(escape, "ESCAPE");
        getRootPane().getActionMap().put("ESCAPE", cancelAction);

        
        
        panel.add(buttonsPanel, BorderLayout.SOUTH);
        setContentPane(panel);
//        setResizable(false);
        setPreferredSize(new Dimension(500, 400));
        pack();

        final Dimension size = getSize();
        final Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
        final int locX = (screen.width - size.width) / 2;
        final int locY = (screen.height - size.height) / 2;
        setLocation(locX, locY);
    }

    private Component createBackupDestinationTab() {
        JPanel panel = new JPanel(new FlowLayout());
        
        panel.add(new JLabel("Destination folder for the backup:"));
        JPanel dPanel = new JPanel();
        dPanel.setLayout(new BoxLayout(dPanel, BoxLayout.LINE_AXIS));
        
        backupDestFolder = new JTextField(35);
        backupDestFolder.setText(settings.getBackupDestinationFolder()); 
        backupDestFolder.getDocument().addDocumentListener(new DocumentListener() {
            public void changedUpdate(DocumentEvent e) {
                okButton.setEnabled(e.getDocument().getLength() > 0);
            }
            public void insertUpdate(DocumentEvent e) {
                changedUpdate(e);
            }
            public void removeUpdate(DocumentEvent e) {
                changedUpdate(e);
            }
        });
        dPanel.add(backupDestFolder);
        JButton chooseDirButton = new JButton(PicBack.DIRECTORY_ICON);
        chooseDirButton.addActionListener(new AbstractAction() {
            private static final long serialVersionUID = 1L;
            public void actionPerformed(ActionEvent e) {
                JFileChooser dc = new JFileChooser();
                dc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                dc.setDialogTitle("Choose the backup destination folder");
                int confirm = dc.showDialog(SettingsDialog.this, "OK");
                if (confirm == JFileChooser.APPROVE_OPTION) {
                    backupDestFolder.setText(dc.getSelectedFile().getPath()); 
                }

//                String dir = destDir.getText().trim();
//                if (dir.length() > 0) {
//                    File fdir = new File(dir);
//                    if (!fdir.exists()  &&  !fdir.mkdir()) {
//                        JMsgPane.showProblemDialog(
//                                SettingsDialog.this,
//                                "Could not create destination directory '" + dir + "'. " + 
//                                "Either the name of the directory is invalid or the current user " +
//                                "has not enough permissions. To avoid the problem, please, choose " +
//                                "another project location or another project name!");
//                        destDir.requestFocus();
//    //                    ok = false;
//                    }
//                }
            }
        });
        dPanel.add(chooseDirButton);
        panel.add(dPanel);
        
        return panel;
    }

    private Component createFoldersTab() {
        JPanel panel = new JPanel(new BorderLayout());
        
        SpringLayout layout = new SpringLayout();
        JPanel tablePanel = new JPanel(layout);
       
        tableModel = new SettingsTableModel();
        foldersTable = new FancyTable(tableModel);
        foldersTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
        foldersTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        
        JScrollPane scrollPane = new JScrollPane(foldersTable);
//        scrollPane.setPreferredSize(new Dimension(400, 300));

        layout.putConstraint(SpringLayout.NORTH, scrollPane, 10, SpringLayout.NORTH, tablePanel);
        layout.putConstraint(SpringLayout.WEST, scrollPane, 10, SpringLayout.WEST, tablePanel);
        layout.putConstraint(SpringLayout.EAST, tablePanel, 10, SpringLayout.EAST, scrollPane);
        layout.putConstraint(SpringLayout.SOUTH, tablePanel, 10, SpringLayout.SOUTH, scrollPane);

        panel.add(scrollPane);
        
        JPanel buttonPanel = new JPanel();
        JButton addButton = new JButton("Add folder(s)");
        addButton.setAlignmentX(JButton.LEFT_ALIGNMENT);
        buttonPanel.add(addButton);
        addButton.addActionListener(new AbstractAction() {
            private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent e) {
                JFileChooser dc = new JFileChooser();
                dc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                dc.setDialogTitle("Add folder(s) to the scan list");
                dc.setMultiSelectionEnabled(true);
                int confirm = dc.showDialog(SettingsDialog.this, "OK");
                if (confirm == JFileChooser.APPROVE_OPTION) {
                    try {
                        for (File file : dc.getSelectedFiles()) {
                            settings.addFolderToScan(file.getPath());
                        }
                        updateFoldersTable();
                    } catch (IOException ex) {
                        JOptionPane.showMessageDialog(SettingsDialog.this,
                                "Couldn't add folder: " + ex.getMessage());
                        logger.error("Couldn't add folder to scan", ex);
                    }
                }
            } 
        });
        
        final JButton removeButton = new JButton("Remove selected");
        buttonPanel.add(removeButton);
        removeButton.addActionListener(new AbstractAction() {
           private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent e) {
                int selectedRow = foldersTable.getSelectedRow();
                if (selectedRow >= 0) {
                    int confirm = JOptionPane.showConfirmDialog(
                            SettingsDialog.this,
                            "Remove selected folder from the scan list?",
                            "Remove folder",
                            JOptionPane.YES_NO_OPTION);
                    if (confirm == JOptionPane.YES_OPTION) {
                        try {
                            settings.removeFolderToScan((String) tableModel.getValueAt(selectedRow, 0));
                            foldersTable.getSelectionModel().clearSelection();
                        } catch (IOException ex) {
                            JOptionPane.showMessageDialog(SettingsDialog.this,
                                    "Couldn't remove folder: " + ex.getMessage());
                            logger.error("Couldn't remove folder to scan", ex);
                        }
                    }
                    updateFoldersTable();
                }
            } 
        });
        addButton.setAlignmentX(JButton.LEFT_ALIGNMENT);
        
        
        panel.add(buttonPanel, BorderLayout.SOUTH);
        return panel;
    }

    private void updateFoldersTable() {
        tableModel.updateFolders();
        tableModel.fireTableDataChanged();
    }

    private class SettingsTableModel extends DefaultTableModel {
        private static final long serialVersionUID = 1L;
        
        private List<String> folders;
        {
            updateFolders();
        }
        
        private void updateFolders() {
            folders = settings.getFoldersToScan();
        }
       
        @Override
        public int getColumnCount() {
            return 1;
        }
        
        @Override
        public String getColumnName(int column) {
            switch (column) {
            case 0: return "Folders with photo albums to scan"; 
            default: return null;
            }
        }
        
        @Override
        public int getRowCount() {
            return settings.getFoldersToScan().size();
        }
        
        @Override
        public Object getValueAt(int row, int column) {
            switch (column) {
            case 0: return folders.get(row); 
            default: return null;
            }
        }
     
        @Override
        public boolean isCellEditable(int row, int column) {
            return false;
        }
    }

}
